

using Newtonsoft.Json;      // 引用命名空间 [dotnet add package Newtonsoft.Json]
using RestSharp;
using System.Collections;
using System.Collections.Generic;
using System.Threading.Tasks;

using System.Diagnostics;
using System.Runtime.CompilerServices;

using UnityEngine;
using UnityEngine.Networking;


namespace AppAPIUtils
{
    public class APIUtils
    {
        public class Values
        {
            // public const int DEFAULT_INT = -9999987;
            public const int client_timeout = 5000;
            public const string base_url = "http://localhost:8000";
            // public const string base_url = "http://www.bodexiong.vip:2201";
        }

        public static async System.Threading.Tasks.Task<IRestResponse> async_send_request(string url, string method = "get", Dictionary<string, object> data = null, Dictionary<string, object> headers = null, int client_timeout = Values.client_timeout)
        {
            var res = new Dictionary<string, object>();
            string full_url = MyRequestUtils.get_full_url(url);

            RestRequest request = MyRequestUtils.get_rest_request(method: method, data: data, headers: headers);

            var response = await async_send_request(url, request, client_timeout: client_timeout);

            // var json = MyRequestUtils.get_response_json_return(response);
            return response;
        }

        public static async System.Threading.Tasks.Task<IRestResponse> async_send_request(string url, RestRequest request, int client_timeout = Values.client_timeout)
        {
            var client = new RestClient(url);
            client.Timeout = client_timeout;

            // 发送异步请求
            IRestResponse response = await client.ExecuteAsync(request);
            BdUtils.log(" --- on async_send_request, response:", response.Content);
            return response;

            // var client = new RestClient(url);
            // var cancellationTokenSource = new System.Threading.CancellationTokenSource();

            // var response =
            //     await client.ExecuteAsync(request, cancellationTokenSource.Token);

            // BdUtils.log(" --- on async_send_request 2, response:", response.Content);

            // // Will output the HTML contents of the requested page
            // // Console.WriteLine(restResponse.Content);
            // return response;
        }

        // public static async System.Threading.Tasks.Task<IRestResponse> async_send_request(string url, Method method, Dictionary<string, object> headers, Dictionary<string, object> data)
        // {
        //     // 创建RestSharp的请求对象
        //     var client = new RestClient(url);
        //     var request = new RestRequest(method);

        //     // 设置请求头
        //     foreach (var header in headers)
        //     {
        //         request.AddHeader(header.Key, header.Value.ToString());
        //     }

        //     // 设置请求数据
        //     foreach (var item in data)
        //     {
        //         request.AddParameter(item.Key, item.Value);
        //     }

        //     // 发送异步请求
        //     // return async_send_request(url, request);
        //     IRestResponse response = await client.ExecuteAsync(request);

        //     return response;
        // }

        // public static async async_request_json(string url, RestRequest request)
        // {

        //     // 发送请求并获取响应
        //     IRestResponse response = await async_send_request(url, request);
        //     return;
        // }

        public class MyRequestUtils
        {
            public static string get_full_url(string url)
            {
                string res;
                if (url.StartsWith("http"))
                    res = url;
                else
                {
                    res = Values.base_url + url;

                    // res = BdUtils.join(Values.base_url, url);
                    // BdUtils.log("!!! url", url, ", res:", res);
                }
                return res;
            }
            // public static string get_response_json_return(string content)
            // {
            //     string json = BdUtils.conv_json_to_dict(content);

            //     // string code = BdUtils.conv_obj_to_string(response.StatusCode);
            //     // BdUtils.assert(code == "OK", $"返回码错误, statusCode: [{response.StatusCode}], ResponseStatus: [{response.ResponseStatus}].");

            //     // var json = response.Content;
            //     // BdUtils.assert(json, $"json[{json}]不能为空! statusCode: [{response.StatusCode}], ResponseStatus: [{response.ResponseStatus}].");
            //     return json;
            // }
            public static string get_response_json_return(IRestResponse response)
            {

                string code = BdUtils.conv_obj_to_string(response.StatusCode);
                BdUtils.assert(code == "OK", $"返回码错误, statusCode: [{response.StatusCode}], ResponseStatus: [{response.ResponseStatus}].");

                var json = response.Content;
                BdUtils.assert(json, $"json[{json}]不能为空! statusCode: [{response.StatusCode}], ResponseStatus: [{response.ResponseStatus}].");
                return json;
            }

            public static RestRequest get_rest_request(string method = "get", Dictionary<string, object> data = null, Dictionary<string, object> headers = null)
            {
                RestRequest request;
                Method _method;

                if (method.ToLower() == "get")
                {
                    _method = Method.GET;
                    request = new RestRequest(_method);
                    if (!BdUtils.is_null(data))
                    {
                        foreach (var kv in data)
                        {
                            // BdUtils.log("key", kv.Key, " --- value:", kv.Value);
                            request.AddQueryParameter(kv.Key, BdUtils.conv_obj_to_string(kv.Value));
                        }
                    }
                }
                else
                {
                    string mtd = method.ToLower();
                    if (mtd == "post")
                        _method = Method.POST;
                    else if (mtd == "put")
                        _method = Method.PUT;
                    else if (mtd == "delete")
                        _method = Method.DELETE;
                    else
                    {
                        throw new System.Exception("method取值必须在[get, post, put, delete]之中!");
                    }

                    request = new RestRequest(_method);

                    request.AddHeader("Content-Type", "application/json");

                    request.AddParameter("application/json", BdUtils.conv_obj_to_json(data), ParameterType.RequestBody);
                }
                return request;
            }

            public delegate void MyResponseAction(IRestResponse response); // 自定义回调委托类型
        }

        public static string request_json(string url, string method = "get", Dictionary<string, object> data = null, Dictionary<string, object> headers = null, int client_timeout = Values.client_timeout, bool async_flag = false, MyRequestUtils.MyResponseAction response_action = null)
        {
            var res = new Dictionary<string, object>();
            string full_url = MyRequestUtils.get_full_url(url);

            RestRequest request = MyRequestUtils.get_rest_request(method: method, data: data, headers: headers);

            var client = new RestClient(full_url);
            client.Timeout = client_timeout;

            var completed_url_with_get_parameters = client.BuildUri(request).ToString();

            // --- 这里尝试用`unity原生请求`解决主线程阻塞问题, 但失败了- -
            // if (false)
            // {
            //     UnityWebRequest u_request;
            //     if (method == "get")
            //     {
            //         BdUtils.log("u_request get completed_url_with_get_parameters:", completed_url_with_get_parameters);

            //         u_request = UnityWebRequest.Get(completed_url_with_get_parameters);
            //     }
            //     else
            //     {
            //         // BdUtils.assert(method == "post", "MethodError: 使用`UnityWebRequest`时, 暂时只支持get和post方法");

            //         // string postData = @'{"remain_money":"65","duration":"16.37755","yong_hu_id":"8007FC47-5D64-5C9A-8C97-33A9048325B4","dong_zuo":"失败","game_level":5}';
            //         // string postData = "{\"yong_hu_id\":\"value\"}";
            //         // string postData = BdUtils.conv_obj_to_json(data);

            //         // 创建一个包含要发送的数据的 Dictionary<string, object>
            //         Dictionary<string, object> dc = new Dictionary<string, object>();
            //         dc["yong_hu_id"] = "123123";

            //         // 将数据转换为 JSON 字符串
            //         string postData = JsonConvert.SerializeObject(dc);

            //         BdUtils.log("u_request post full_url:", full_url, ", data:", postData);

            //         u_request = UnityWebRequest.Post(full_url, postData: postData);
            //         // u_request = UnityWebRequest.Post(full_url, "");

            //         // u_request = UnityWebRequest.Post(url, UnityWebRequest.kHttpVerbPOST);

            //         // byte[] postBytes = System.Text.Encoding.UTF8.GetBytes(postData);
            //         // u_request.uploadHandler = new UploadHandlerRaw(postBytes);
            //         // u_request.downloadHandler = new DownloadHandlerBuffer();

            //         u_request.SetRequestHeader("Content-Type", "application/json");  // 设置请求头，指定数据类型为 JSON
            //     }
            //     u_request.SendWebRequest();//读取数据

            //     while (!u_request.isDone) { }

            //     if (u_request.error == null)//是否读取完数据
            //     {
            //         // File.WriteAllText(toPath, request.downloadHandler.text);
            //         string json = u_request.downloadHandler.text;
            //         // var json = MyRequestUtils.get_response_json_return(response);

            //         BdUtils.log(" ~~~ u_request json:", json);
            //         return json;
            //     }
            //     else
            //     {
            //         BdUtils.log(" *** u_request error:", u_request.error);
            //         return "";
            //     }
            // }

            // --- 这里尝试用`异步方案`解决主线程阻塞问题, 但失败了- -
            if (async_flag)
            {
                var task = async_send_request(url, request, client_timeout: client_timeout);

                task.ContinueWith(t =>
                {
                    // BdUtils.assert(!t.IsFaulted, $"异步请求错误? url: {url}");

                    // 异步方法完成后执行的逻辑
                    if (t.IsFaulted)
                    {
                        BdUtils.log($"异步请求错误? url: {url}");
                    }
                    else
                    {
                        System.Threading.Thread.Sleep(1000);

                        var response = t.Result;

                        BdUtils.log($"异步请求url[{url}]成功! response.Content:", response.Content);

                        if (response_action != null)
                            response_action(response);
                    }
                });

                return "";
            }
            else
            {
                IRestResponse response = client.Execute(request);
                var json = MyRequestUtils.get_response_json_return(response);
                return json;
            }
        }

        public static Dictionary<string, object> request_dict(string url, string method = "get", Dictionary<string, object> data = null, Dictionary<string, object> headers = null, int client_timeout = Values.client_timeout, bool async_flag = false, MyRequestUtils.MyResponseAction response_action = null)
        {
            var response_json = request_json(url: url, method: method, data: data, headers: headers, client_timeout: client_timeout, async_flag: async_flag, response_action: response_action);

            var response_dc = BdUtils.conv_json_to_dict(response_json);
            // BdUtils.log("MyJson conv_json_to_dict --- ", BdUtils.conv_json_to_dict(response_json));

            return response_dc;
        }

        public static bool is_normal_api_status_code(int status_code)
        {
            return status_code == 200 || status_code == 201;
        }

        public static MyListView.MyListResponse request_list_view(string url, string method = "get", Dictionary<string, object> data = null, Dictionary<string, object> headers = null, int client_timeout = Values.client_timeout)
        {
            var response_json = request_json(url: url, method: method, data: data, headers: headers, client_timeout: client_timeout);

            var response = JsonConvert.DeserializeObject<MyListView.MyListResponse>(response_json);
            BdUtils.assert(is_normal_api_status_code(response.status), $"api的status[{response.status}]取值不在[200, 201]之中!");
            return response;
        }
        public static MyRetrieveView.MyRetrieveResponse request_retrieve_view(string url, string method = "get", Dictionary<string, object> data = null, Dictionary<string, object> headers = null, int client_timeout = Values.client_timeout)
        {
            var response_json = request_json(url: url, method: method, data: data, headers: headers, client_timeout: client_timeout);

            var response = JsonConvert.DeserializeObject<MyRetrieveView.MyRetrieveResponse>(response_json);
            BdUtils.assert(is_normal_api_status_code(response.status), $"api的status[{response.status}]取值不在[200, 201]之中!");
            return response;
        }


    }

    public class MyRetrieveView
    {
        public class MyRetrieveResponse : BdUtils.IJson
        {

            public int status { get; set; }

            public string msg { get; set; }

            public Dictionary<string, object> result { get; set; }

        }
    }

    public class MyPageDc : BdUtils.IJson
    {
        public int count_items { get; set; }
        public int total_pages { get; set; }
        public int page_size { get; set; }
        public int p { get; set; }
    }

    public class MyListView
    {
        public class MyListResult : BdUtils.IJson
        {
            public MyPageDc page_dc { get; set; }
            // public Dictionary<string, int> page_dc { get; set; }

            public List<Dictionary<string, object>> data { get; set; }
            // public List<MyObject> data { get; set; }
        }
        public class MyListResponse : BdUtils.IJson
        {

            public int status { get; set; }

            public string msg { get; set; }

            public MyListResult result { get; set; }
            // public Dictionary<string, MyResult> result { get; set; }
        }
    }


    public class MyBaseResponse : BdUtils.IJson
    {

        public int status { get; set; }

        public string msg { get; set; }

        // public MyResult result { get; set; }
        public Dictionary<string, object> result { get; set; }
    }

}


